package com.lwbldy.common.tools;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * <p>@ClassName  SignUtil </p>
 * <p>@Author   郭志威 </p>
 * <p>@Date     2020/6/21 0021 21:24 </p>
 * <p>@Description
 */
public class SignUtil {
    private static final String KEY_ALGORITHM = "RSA";
    private static final String SIGNATURE_ALGORITHM = "MD5withRSA";
    public static String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXHQd0kDq+CQmAyWAhUNyxKBdWAdMCnMRYlPKxW9j3kpKVHMDFng5oTS7YxAlxVL0H4MDxSZFgTLWAbWLhCHi+L8f0X+x27Ke7H3T+VHjAJD2w2+O2L7QlihBeMH4sZi+nQGjwP/tmIcgLYV6WUrDcdOtiik24Uj7Sz5fg8XXclwIDAQAB";
    public static String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANcdB3SQOr4JCYDJYCFQ3LEoF1YB0wKcxFiU8rFb2PeSkpUcwMWeDmhNLtjECXFUvQfgwPFJkWBMtYBtYuEIeL4vx/Rf7Hbsp7sfdP5UeMAkPbDb47YvtCWKEF4wfixmL6dAaPA/+2YhyAthXpZSsNx062KKTbhSPtLPl+DxddyXAgMBAAECgYBzi1Iv2DDVVoFWPdR20LpaJhCyz/QJmS8V7ZuWjKE0CfTWR0V8YHOYrqyVHmd8CmomyyCX+k4uDcYIH7lW6nf/o0kaylLMl1M4ITRTJ4PdQURRxej+nAKxMQy03bmdBZ9vKP6jjsqWo+ZuaFiEnyyMyHOuVFCkK3Xz+anaUKmc4QJBAP2xYSQS1s+XESu4HJibcnNQsjI5VBoRbyVutJ+L1wpqyYO320SGYCo13xvlRROyTRxdjFw9JHZss1LoujKsDkkCQQDZEdVBij+uhv0HJs7E0QlpEFhfUoehpbMuPD5IKWxNCDADTq78I8CHCApVRvTytr0neiM1VHugZ7Q83RVcVhPfAkEAr6hcPKAWwNI2/3CRzFEF5DahzAjJ5OrhbKfExRwMn5flRCDP4BizCUcX3rbXJ5YzskpL36ouTxlg6S1fj6p2kQJBAL5ROFzCTZtDl01R5TAC5vFK93B795bupO8AusqiJuZTK2V680j2P7MkhYrHL7QuLCIUoBH+BHZa9lf2rufKQJkCQG6cUM0TdWlsck/oDYawdMnKTLyJLQdrV8h8DGxvEnUgBlmFZEC/03j3HVhcajDG38Z+F1rtiVuUak9pYiIBRPc=";
    public static void main(String[] args) {
        String data = "adsad";
        String sign = sign(data, privateKey);
        System.out.println(sign);
        System.out.println(verifySign(data, publicKey, sign));
    }

    private static String sign(byte[] data, String privateKey) {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(privateKey);
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initSign(priKey);
            signature.update(data);
            return Base64.getEncoder().encodeToString(signature.sign());
        } catch (Exception e) {
            System.out.println(e.getMessage());
            throw new IllegalAccessError("生成RSA密钥签名失败!");
        }
    }

    public static boolean verifySign(String data, String publicKey, String sign) {
        boolean flag = false;
        // 初次验签
        try {
            flag = verifySign(data.getBytes("GBK"), Base64.getDecoder().decode(publicKey), Base64.getDecoder().decode(sign));
        } catch (Exception e) {
            System.out.println("一次Base64转码的校验RSA密钥验签异常，开始二次验签。");

        }
        // 二次验签（由于有部分对接工作对签名采用BsBase64二次转码，故此处二次验签，增加系统兼容性）
        if (!flag) {
            try {
                flag = verifySign(data.getBytes("GBK"), Base64.getDecoder().decode(publicKey), Base64.getDecoder().decode(Base64.getDecoder().decode(sign)));
            } catch (Exception e) {
                System.out.println("二次Base64转码校验RSA密钥验签异常: " + e.getMessage());
            }
            if (flag) {
                System.out.println("二次Base64转码校验RSA密钥验签成功。");
            }
        }
        return flag;
    }

    public static String sign(String data, String privateKey) {
        try {
            return sign(data.getBytes("GBK"), privateKey);
        } catch (Exception e) {
            throw new IllegalAccessError("BASE64加密失败!");
        }
    }

    private static boolean verifySign(byte[] data, byte[] publicKey, byte[] sign) throws Exception {
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PublicKey pubKey = keyFactory.generatePublic(keySpec);
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(pubKey);
        signature.update(data);
        return signature.verify(sign);
    }
}
